﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

using Aliphant.Interfaces;
using Aliphant.Script.Models;

using Microsoft.ClearScript;
using Microsoft.ClearScript.V8;

using static System.Runtime.InteropServices.JavaScript.JSType;
using static Microsoft.ClearScript.V8.V8CpuProfile;

namespace Aliphant.Script
{
    public class ScriptAgent : IScriptAgent
    {
        private IScriptEngine engine;

        public ScriptAgent(IScriptEngine engine)
        {
            this.engine = engine;
        }

        public void InitHost()
        {
            string[] wpf = { "mscorlib", "System.Core", "PresentationCore", "PresentationFramework", "WindowsBase", "System.Runtime", "System.Threading.Tasks" };
            engine.AddHostObject("wpf", new HostTypeCollection(wpf));     // 加载C#的程序集
        }

        public void RegisterObject(dynamic @object)
        {
            engine.AddHostObject("local", @object);
        }

        public void RegisterEnv(string[] dlls)
        {
            HostTypeCollection hostTypes = new HostTypeCollection();
            LoadSelfAssmbly(hostTypes, dlls);
            engine.AddHostObject("env", hostTypes);
        }

        public void RegisterTools(IScriptTool tools)
        {
            engine.AddHostObject("tools", tools);
        }

        public object Execute(string path)
        {
            string code = Load(path);
            return engine.Evaluate(code);
        }

        public object Evaluate(string code)
        {
            return engine.Evaluate(code);
        }


        public void Dispose()
        {
            engine.Dispose();
        }

        #region 静态方法

        public static IScriptAgent ScriptAgentFactory()
        {
            IScriptEngine engine = new V8ScriptEngine(V8ScriptEngineFlags.UseCaseInsensitiveMemberBinding | V8ScriptEngineFlags.EnableTaskPromiseConversion);
            IScriptAgent agent = new ScriptAgent(engine);
            agent.InitHost();

            //IScriptTool tools = new ScriptTools();
            agent.RegisterTools(ScriptTools.Instance);

            return agent;
        }

        /// <summary>
        /// 加载JS文件
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public static string Load(string path)
        {
            return File.ReadAllText(path);
        }

        /// <summary>
        /// 异步加载JS文件
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public async static Task<string> LoadAsync(string path)
        {
            return await File.ReadAllTextAsync(path);
        }

        #endregion

        private void LoadSelfAssmbly(HostTypeCollection hostTypes, string[] assmblies)
        {
            Array.ForEach(assmblies, (a) =>
            {
                string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, a + ".dll");
                Assembly assembly = Assembly.LoadFile(path);
                hostTypes.AddAssembly(assembly);
            });
        }


    }
}
